package org.linlinjava.litemall.wx.service;


import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.linlinjava.litemall.core.util.DistributedLockHandler;
import org.linlinjava.litemall.core.util.RedisUntil;
import org.linlinjava.litemall.core.util.UncDate;
import org.linlinjava.litemall.core.vo.Lock;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.po.MngUserCutpricePo;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.util.*;
import org.linlinjava.litemall.wx.vo.Coupon;
import org.linlinjava.litemall.wx.vo.wechart.EnterprisePayment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.net.NetworkInterface;
import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.SocketException;
import java.security.KeyStore;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

import static org.linlinjava.litemall.wx.util.Sign.createLinkString;
import static org.linlinjava.litemall.wx.util.Sign.paraFilter;

@Service
public class WxGiveRedPackService {
    private final Log logger = LogFactory.getLog(WxRedPacaketsService.class);
    @Autowired
    private SystemWxConfigService systemWxConfigService;
    @Autowired
    private LitemallRedPacaketsHistoryService litemallRedPacaketsHistoryService;
    @Autowired
    private LitemallRedPacaketsService litemallRedPacaketsService;
    @Autowired
    private RedisUntil redisUntil;
    @Autowired
    private LitemallUserService litemallUserService;
    @Autowired
    private DistributedLockHandler distributedLockHandler;
    @Autowired
    private ReceiveRecordService receiveRecordService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    private String message;
    private String enterprisePaymentMessage;

    public String getEnterprisePaymentMessage() {
        return enterprisePaymentMessage;
    }

    public void setEnterprisePaymentMessage(String enterprisePaymentMessage) {
        this.enterprisePaymentMessage = enterprisePaymentMessage;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    public ReceiveRecord receivingSpeedRace(String userid, LitemallRedPacaketsHistory spfc) throws Exception {
        LitemallRedPacakets platformCutprice = litemallRedPacaketsService.findById(spfc.getCutpriceId());
        ReceiveRecord receiveRecord = null;
        Lock lock = new Lock("BIZ:LOCK:RACELOCK" + spfc.getId(),
                "BIZ:LOCK:RACELOCK" + spfc.getId());
        logger.info("获取 BIZ:LOCK:RACELOCK" + spfc.getId());
        try {
            if (distributedLockHandler.tryLock(lock, 3000, 100)) {
                receiveRecord = receiveRecordService.findReceiveRecordByBargainByBargainListIdAndOpenid(spfc.getId(), userid);
                logger.info("receiveRecord:" + receiveRecord);
                if (receiveRecord != null) {
                    this.setEnterprisePaymentMessage("不能重复领取");
                    return null;
                } else {
                    receiveRecord = new ReceiveRecord();
                }
                //获取剩余数量
                int receivableNum = 0;
                int flag = 0;
                List<Integer> randomPrice = new ArrayList<>();
                if (redisUntil.get("redPackage_" + spfc.getId()) != null) {
                    Map<String, Object> redPackageMap = (Map<String, Object>) redisUntil.get("redPackage_" + spfc.getId());
                    receivableNum = (int) redPackageMap.get("receivableNum");
                    //获取随机金额列表
                    randomPrice = (List<Integer>) redPackageMap.get("randomPrice");
                    logger.info("receivableNum:" + receivableNum + " randomPrice:" + randomPrice);
                } else {
                    logger.info("receivableNum为空");
                    this.setEnterprisePaymentMessage("你动作慢了，红包已被抢完了");
                    return null;
                }
                logger.info("receivableNum" + receivableNum + "UncDate.getDateCount(spfc.getFinishTime(),new Date())/1000" + UncDate.getDateCount(Timestamp.valueOf(spfc.getFinishTime()), new Date()) / 1000 + "  platformCutprice.getDeadline():" + platformCutprice.getDeadline());
                //platformCutprice.getDeadline()==0时不限制
                if (receivableNum > 0 && (UncDate.getDateCount(Timestamp.valueOf(spfc.getFinishTime()), new Date()) / 1000 <= platformCutprice.getDeadline() || platformCutprice.getDeadline() == 0)) {
                    //##获取参与人列表,查询该用户是否可领取
                    logger.info("receivableNum" + receivableNum + " ============");
                    List<String> userIdsCanDo = this.getUserIdsCanDo(platformCutprice.getId(), platformCutprice.getAuction(), spfc.getId(), spfc.getUserId(), "");
                    logger.info("userIdsCanDo" + userIdsCanDo + "  userid:" + userid);
                    if (userIdsCanDo != null && userIdsCanDo.size() > 0) {
                        for (String userIdCanDo : userIdsCanDo) {
                            if (userid.equals(userIdCanDo)) {
                                flag = 1;
                            }
                        }
                    }
                    logger.info("flag====" + flag);
                    if (flag == 1) {
                        receiveRecord.setBargainListId(spfc.getId());
                        receiveRecord.setCutpriceId(platformCutprice.getId());
                        receiveRecord.setFinishTime(LocalDateTime.now());
                        receiveRecord.setStatus(0);
                        receiveRecord.setOpenid(userid);
                        receiveRecord.setPrice(randomPrice.get(0));
                        logger.info("receiveRecords:" + receiveRecord);
                        receiveRecordService.insertByRecord(receiveRecord);

                        //设置redis
                        receivableNum -= 1;
                        randomPrice.remove(0);
                        logger.info("receivableNum:" + receivableNum + " randomPrice:" + randomPrice);
                        Map<String, Object> redPackageMap = new HashMap<>();
                        if (randomPrice.size() == receivableNum && receivableNum > 0) {
                            redPackageMap.put("receivableNum", receivableNum);
                            redPackageMap.put("randomPrice", randomPrice);
                            logger.info("redPackageMap:" + redPackageMap);
                            redisUntil.set("redPackage_" + spfc.getId(), redPackageMap, platformCutprice.getDuration() + platformCutprice.getDeadline());
                        } else if (receivableNum <= 0) {
                            logger.info("delete前 " + "redPackage_" + spfc.getId());
                            redisUntil.delete("redPackage_" + spfc.getId());
                            logger.info("delete后 " + "redPackage_" + spfc.getId());
                        }
                    } else {
                        logger.error("flag==0");
                    }
                } else {
                    this.setEnterprisePaymentMessage("你动作慢了，红包已被领完了");
                    return null;
                }

            } else {
                logger.error("cannot get lock!" + userid);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            distributedLockHandler.releaseLock(lock);
            logger.info("releaseLock(lock) +" + System.currentTimeMillis());
        }
        return receiveRecord;
    }


    /**
     * @Description: getUserIdsCanDo 获取活动所有人
     * @param: [platformCutprice, spfc, userid]
     * @return: java.util.List
     * @auther: caiy
     * @date: 2019/7/25 0025 16:04
     */
    public List getUserIdsCanDo(long platformCutpriceId, int auction, long hisId, String hisUserId, String userid) throws Exception {
        //##获取参与人列表
        BoundHashOperations<String, Object, Object> boundHashOps = redisTemplate.boundHashOps(
                "Pl_" + platformCutpriceId + "_" + auction + "_" + hisId);
        Map<Object, Object> map = boundHashOps.entries();
        List<String> userIds = new ArrayList<>();
        if (StringUtils.isNotBlank(userid) && !userid.equals(hisUserId)) {
            userIds.add(userid);
        }
        if (boundHashOps != null) {
            for (Object o : map.keySet()) {
                String userId = (String) o;
                if (!hisUserId.equals(userId) && StringUtils.isNotBlank(userId)) {
                    userIds.add(userId);
                }
            }
        }
        //##获取随机用户
        List<String> userIdsCanDo = new ArrayList<>();
        userIdsCanDo = userIds;
        userIdsCanDo.add(hisUserId);
        logger.info("userIdsCanDo:" + userIdsCanDo);
        return userIdsCanDo;
    }


    public Map<String, Object> enterprisePaymentSpecial(LitemallRedPacaketsHistory sph, SysWxConfig wxConfig,  ReceiveRecord receiveRecord) throws Exception {
        logger.info("receiveRecord" + receiveRecord);
        Map<String, Object> returnMap = new HashMap<>();
        int flag = 0;
        LitemallRedPacakets one = litemallRedPacaketsService.findById(sph.getCutpriceId());
        // SysConsumer 	consumer  = consumerDao.findByUserId(sph.getUserId());
        UUIDHexGenerator uuidGenerator = new UUIDHexGenerator();
        String nonceStr = uuidGenerator.generate();
        TreeMap<String, String> p = new TreeMap<String, String>();
        p.put("mch_appid", wxConfig.getWxSubappid());
        p.put("mchid", wxConfig.getWxSubmchid());
        p.put("nonce_str", nonceStr);
        p.put("partner_trade_no", this.getPartnerTradeNo(wxConfig.getWxSubmchid()));
        returnMap.put("partner_trade_no", p.get("partner_trade_no"));
        //String userId = "ohKTy5E2oEPz0h9iL655oeFj2QiI";
        //p.put("openid", userId);
        p.put("openid", receiveRecord.getOpenid());
        p.put("check_name", "NO_CHECK");
        p.put("amount", receiveRecord.getPrice() + "");
        p.put("desc", one.getSubtitleSponser());
        p.put("spbill_create_ip", getLocalIpAddr());
        //String sign = WXPayUtil.generateSignature(p, wxConfig.getWxSecret());
//    p.put("sign", sign);
        Map<String, String> sPara = paraFilter(p);
        String prestr = createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        String key = "&key=" + wxConfig.getWxMchkey(); // 商户支付密钥
        String mysign = Sign.sign(prestr, key, "utf-8").toUpperCase();

        EnterprisePayment enterprisePayment = new EnterprisePayment();
        enterprisePayment.setMchid(p.get("mchid"));
        enterprisePayment.setMch_appid(p.get("mch_appid"));
        enterprisePayment.setNonce_str(p.get("nonce_str"));
        enterprisePayment.setPartner_trade_no(p.get("partner_trade_no"));
        enterprisePayment.setOpenid(p.get("openid"));
        enterprisePayment.setCheck_name(p.get("check_name"));
        enterprisePayment.setAmount(p.get("amount"));
        enterprisePayment.setDesc(p.get("desc"));
        enterprisePayment.setSpbill_create_ip(p.get("spbill_create_ip"));
        enterprisePayment.setSign(mysign);
        //returnMap = this.enterprisePayment(p);
// 文本消息对象转换成xml
        String respXml = MessageUtil.messageToXml(enterprisePayment);

        // 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
        respXml = respXml.replace("__", "_");
        logger.info(respXml);
        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File(wxConfig.getWxSubcertpath())); // 此处为证书所放的绝对路径
        try {
            keyStore.load(instream, enterprisePayment.getMchid().toCharArray());
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, enterprisePayment.getMchid().toCharArray())
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        try {

            // 企业付款接口地址
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers");

            StringEntity reqEntity = new StringEntity(respXml, "utf-8");

            logger.info(" 企业付款状态：" + respXml);
            // 设置类型
            reqEntity.setContentType("application/x-www-form-urlencoded");

            httpPost.setEntity(reqEntity);

            logger.info("executing request" + httpPost.getRequestLine());

            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                logger.info(response.getStatusLine());
                if (entity != null) {

                    // 从request中取得输入流
                    InputStream inputStream = entity.getContent();
                    // 读取输入流
                    SAXReader reader = new SAXReader();
                    Document document = reader.read(inputStream);
                    // 得到xml根元素
                    Element root = document.getRootElement();
                    // 得到根元素的所有子节点
                    List<Element> elementList = root.elements();

                    // 遍历所有子节点
                    for (Element e : elementList)
                        map.put(e.getName(), e.getText());

                    // 释放资源
                    inputStream.close();
                    inputStream = null;

                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        logger.info(map);
        // 返回状态码
        String return_code = map.get("return_code");
        if (StringUtils.isNotBlank(return_code)) {
            if (!"SUCCESS".equals(return_code)) {
                logger.error("通信FAIL");
            } else {
                // 业务结果
                String result_code = map.get("result_code");
                logger.info(result_code + "  " + return_code);
                if (StringUtils.isNotBlank(result_code) && "SUCCESS".equals(result_code)) {
                    if ("SUCCESS".equals(return_code)) {
                        logger.info(result_code + "  " + return_code);
                        logger.info(map);
                        flag = 1;
                        returnMap.put("flag", flag);
                        returnMap.put("price", receiveRecord.getPrice());
                        logger.info("returnMap" + returnMap);
                        return returnMap;
                    }
                }
                // 错误代码
                String err_code = map.get("err_code");
                logger.error(err_code);
                // 错误代码描述
                String err_code_des = map.get("err_code_des");
                logger.error(err_code);
            }
        }
        // 返回信息
        String return_msg = map.get("return_msg");
        if (StringUtils.isNotBlank(return_msg)) {
            logger.error(return_msg);
        }
        returnMap.put("flag", flag);
        returnMap.put("price", receiveRecord.getPrice());
        logger.info(returnMap);
        return returnMap;
    }

    public int enterprisePayment(LitemallRedPacaketsHistory sph, SysWxConfig wxConfig) throws Exception {
        Map<String, String> returnMap = null;
        LitemallRedPacakets one = litemallRedPacaketsService.findById(sph.getCutpriceId());


        //WxUserAssoc  wxUserAssoc = wxUserAssocDao.findByWxUserId(sph.getUserId());
        LitemallUser consumer = litemallUserService.findUserByOpenId(sph.getUserId());

        //WxUserAssoc  wxUserAssoc = wxUserAssocDao.findByUnionid(consumer.getUnionId());
        UUIDHexGenerator uuidGenerator = new UUIDHexGenerator();
        String nonceStr = uuidGenerator.generate();
        //String non=PayCommonUtil.CreateNoncestr();
        TreeMap<String, String> p = new TreeMap<String, String>();
        p.put("mch_appid", wxConfig.getWxSubappid());
        p.put("mchid", wxConfig.getWxSubmchid());
        p.put("nonce_str", nonceStr);
        p.put("partner_trade_no", sph.getPartnerTradeNo());
        p.put("openid", sph.getUserId());
        p.put("check_name", "NO_CHECK");
        p.put("amount", sph.getPrice() + "");
        p.put("desc", one.getSubtitleSponser());
        p.put("spbill_create_ip", getLocalIpAddr());
        //String sign = WXPayUtil.generateSignature(p, wxConfig.getWxSecret());
//    p.put("sign", sign);
        Map<String, String> sPara = paraFilter(p);
        String prestr = createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        String key = "&key=" + wxConfig.getWxMchkey(); // 商户支付密钥
        String mysign = Sign.sign(prestr, key, "utf-8").toUpperCase();

        EnterprisePayment enterprisePayment = new EnterprisePayment();
        enterprisePayment.setMchid(p.get("mchid"));
        enterprisePayment.setMch_appid(p.get("mch_appid"));
        enterprisePayment.setNonce_str(p.get("nonce_str"));
        enterprisePayment.setPartner_trade_no(p.get("partner_trade_no"));
        enterprisePayment.setOpenid(p.get("openid"));
        enterprisePayment.setCheck_name(p.get("check_name"));
        enterprisePayment.setAmount(p.get("amount"));
        enterprisePayment.setDesc(p.get("desc"));
        enterprisePayment.setSpbill_create_ip(p.get("spbill_create_ip"));
        enterprisePayment.setSign(mysign);
        //returnMap = this.enterprisePayment(p);
// 文本消息对象转换成xml
        String respXml = MessageUtil.messageToXml(enterprisePayment);

        // 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
        respXml = respXml.replace("__", "_");
        //logger.info(respXml);
        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File(wxConfig.getWxSubcertpath())); // 此处为证书所放的绝对路径
        try {
            keyStore.load(instream, enterprisePayment.getMchid().toCharArray());
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, enterprisePayment.getMchid().toCharArray())
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        try {

            // 企业付款接口地址
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers");

            StringEntity reqEntity = new StringEntity(respXml, "utf-8");

            //logger.info(" 企业付款状态：" + respXml);
            // 设置类型
            reqEntity.setContentType("application/x-www-form-urlencoded");

            httpPost.setEntity(reqEntity);

            //logger.info("executing request" + httpPost.getRequestLine());

            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                logger.info(response.getStatusLine());
                if (entity != null) {

                    // 从request中取得输入流
                    InputStream inputStream = entity.getContent();
                    // 读取输入流
                    SAXReader reader = new SAXReader();
                    Document document = reader.read(inputStream);
                    // 得到xml根元素
                    Element root = document.getRootElement();
                    // 得到根元素的所有子节点
                    List<Element> elementList = root.elements();

                    // 遍历所有子节点
                    for (Element e : elementList)
                        map.put(e.getName(), e.getText());

                    // 释放资源
                    inputStream.close();
                    inputStream = null;

                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        logger.info(map);
        // 返回状态码
        String return_code = map.get("return_code");
        if (StringUtils.isNotBlank(return_code)) {
            if (!"SUCCESS".equals(return_code)) {
                logger.error("通信FAIL");
            } else {
                // 业务结果
                String result_code = map.get("result_code");
                logger.info(result_code + "  " + return_code);
                if (StringUtils.isNotBlank(result_code) && "SUCCESS".equals(result_code)) {
                    if ("SUCCESS".equals(return_code)) {
                        logger.info(result_code + "  " + return_code);
                        logger.info(map);
                        return 1;
                    }
                }
                // 错误代码
                String err_code = map.get("err_code");
                logger.error(err_code);
                // 错误代码描述
                String err_code_des = map.get("err_code_des");
                logger.error(err_code);
            }
        }
        // 返回信息
        String return_msg = map.get("return_msg");
        if (StringUtils.isNotBlank(return_msg)) {
            logger.error(return_msg);
        }
        return 0;
    }

    public static String getLocalIpAddr() {

        String clientIP = null;
        Enumeration<NetworkInterface> networks = null;
        try {
            // 获取所有网卡设备
            networks = NetworkInterface.getNetworkInterfaces();
            if (networks == null) {
                // 没有网卡设备 打印日志 返回null结束
                //logger.info("networks  is null");
                return null;
            }
        } catch (SocketException e) {
          //  log.error(e.getMessage());
        }
        InetAddress ip;
        Enumeration<InetAddress> addrs;
        // 遍历网卡设备
        while (networks.hasMoreElements()) {
            NetworkInterface ni = networks.nextElement();
            try {
                // 过滤掉 loopback设备、虚拟网卡
                if (!ni.isUp() || ni.isLoopback() || ni.isVirtual()) {
                    continue;
                }
            } catch (SocketException e) {
               // log.info(e.getMessage());
            }
            addrs = ni.getInetAddresses();
            if (addrs == null) {
               // log.info("InetAddress is null");
                continue;
            }
            // 遍历InetAddress信息
            while (addrs.hasMoreElements()) {
                ip = addrs.nextElement();
                if (!ip.isLoopbackAddress() && ip.isSiteLocalAddress() && ip.getHostAddress().indexOf(":") == -1) {
                    try {
                        clientIP = ip.toString().split("/")[1];
                    } catch (ArrayIndexOutOfBoundsException e) {
                        clientIP = null;
                    }
                }
            }
        }
       // log.info("clientIP:" + clientIP);
        // System.out.println(clientIP);
        return clientIP;
    }
    /**
     *
     * 领取微信优惠券
     * */
    public int giveCoupon(Long userItemListId, String appletName) throws Exception {
        int flag = 0;
        Map<String, String> returnMap = null;

        SysWxConfig wxConfig = systemWxConfigService.getconfigByAppletNam(appletName);

        LitemallRedPacaketsHistory spf = litemallRedPacaketsHistoryService.getCutRedpacaketById(userItemListId);
        LitemallRedPacakets platformCutprices = litemallRedPacaketsService.findById(spf.getId());
        if (spf.getStatus() != 1 && spf.getCutpriceMode() == 3) {
            logger.error("spf:" + spf.getId() + "spf.getStatus()&& spf.getCutpriceMode()" + spf.getStatus() + spf.getCutpriceMode());
            return flag;
        }
        // WxUserAssoc wxUserAssoc = wxUserAssocDao.findByWxUserId(spf.getUserId());
     /*if (wxUserAssoc == null) {
       logger.error("未关注公众号");
       return flag;
     }*/
        //String non=PayCommonUtil.CreateNoncestr();
        TreeMap<String, String> p = new TreeMap<String, String>();
        p.put("coupon_stock_id", spf.getBatchId());
        p.put("openid_count", "1");
        p.put("partner_trade_no", this.getPartnerTradeNo(wxConfig.getWxSubmchid()));
        //p.put("openid", wxUserAssoc.getUserId());
        p.put("openid", spf.getUserId());
        //p.put("appid", wxConfig.getWxAppid());
        p.put("appid", wxConfig.getWxSubappid());
        // p.put("mch_id", GlobalValue.wxMchID);
        p.put("mch_id", wxConfig.getWxSubmchid());
        p.put("device_info", "1");
        p.put("nonce_str", UUIDHexGenerator.generate());
        Map<String, String> sPara = paraFilter(p);
        String prestr = createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        String key = "&key=" + wxConfig.getWxMchkey(); // 商户支付密钥
        String mysign = Sign.sign(prestr, key, "utf-8").toUpperCase();
        String sign = WXPayUtil.generateSignature(p, wxConfig.getWxSecret());
        p.put("sign", mysign);
        Coupon coupon = new Coupon();
        coupon.setAppid(p.get("appid"));
        coupon.setCoupon_stock_id(p.get("coupon_stock_id"));
        coupon.setDevice_info(p.get("device_info"));
        coupon.setMch_id(p.get("mch_id"));
        coupon.setNonce_str(p.get("nonce_str"));
        coupon.setOpenid(p.get("openid"));
        coupon.setOpenid_count(p.get("openid_count"));
        coupon.setSign(p.get("sign"));
        coupon.setPartner_trade_no(p.get("partner_trade_no"));
        String respXml = MessageUtil.messageToXml(coupon);
        // 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
        respXml = respXml.replace("__", "_");
        logger.info(respXml);
        String uri = "https://api.mch.weixin.qq.com/mmpaymkttransfers/send_coupon";
        flag = this.wxDo(wxConfig.getWxSubcertpath(), respXml, p.get("mch_id"), uri);
        if (flag == 1) {
            MngUserCutpricePo userCutprice = (MngUserCutpricePo) redisUntil.get(
                    "Pl_set_" + spf.getCutpriceId() + "_" + platformCutprices.getAuction() + "_" + spf.getId());
            //logger.info("userCutprice" + userCutprice);
            if (userCutprice != null) {
                logger.info("Pl_set_" + spf.getCutpriceId() + "_" + platformCutprices.getAuction() + "_" + spf.getId() + "redis已重置");
                userCutprice.setStatus(0);
                redisUntil.setSeconds("Pl_set_" + spf.getCutpriceId() + "_" + platformCutprices.getAuction() + "_" + spf.getId(), userCutprice, 24 * 60 * 60);
            }
            spf.setStatus(0);
            spf.setPartnerTradeNo(p.get("partner_trade_no"));
            litemallRedPacaketsHistoryService.updateStatus(spf);

        }
        return flag;

    }

    private int wxDo(String wechatCert, String respXml, String mchid, String uri) throws Exception {
        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        FileInputStream instream = new FileInputStream(new File(wechatCert)); // 此处为证书所放的绝对路径
        try {
            keyStore.load(instream, mchid.toCharArray());
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchid.toCharArray())
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        try {

            // 企业付款接口地址
            HttpPost httpPost = new HttpPost(uri);

            StringEntity reqEntity = new StringEntity(respXml, "utf-8");

          //  logger.info(" 企业付款状态：" + respXml);
            // 设置类型
            reqEntity.setContentType("application/x-www-form-urlencoded");

            httpPost.setEntity(reqEntity);

           // logger.info("executing request" + httpPost.getRequestLine());

            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                logger.info(response.getStatusLine());
                if (entity != null) {

                    // 从request中取得输入流
                    InputStream inputStream = entity.getContent();
                    // 读取输入流
                    SAXReader reader = new SAXReader();
                    Document document = reader.read(inputStream);
                    // 得到xml根元素
                    Element root = document.getRootElement();
                    // 得到根元素的所有子节点
                    List<Element> elementList = root.elements();

                    // 遍历所有子节点
                    for (Element e : elementList)
                        map.put(e.getName(), e.getText());

                    // 释放资源
                    inputStream.close();
                    inputStream = null;

                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        logger.info(map);
        // 返回状态码
        String return_code = map.get("return_code");
        String result_code = map.get("result_code");
        if (StringUtils.isNotBlank(return_code)) {
            if (!"SUCCESS".equals(return_code) || !"SUCCESS".equals(result_code)) {
                logger.error("通信FAIL");
            } else {
                // 业务结果
                if (StringUtils.isNotBlank(result_code)) {
                    if ("SUCCESS".equals(return_code)) {
                        logger.info(map);
                        return 1;
                    }
                }
                // 错误代码
                String err_code = map.get("err_code");
                logger.error(err_code);
                // 错误代码描述
                String err_code_des = map.get("err_code_des");
                logger.error(err_code);
            }
        }
        // 返回信息
        String return_msg = map.get("return_msg");
        if (StringUtils.isNotBlank(return_msg)) {
            logger.error(return_msg);
        }
        return 0;
    }


    private String getPartnerTradeNo(String wxSubmchid) {
        String code = "";
        for (int i = 0; i < 8; i++) {
            code += (int) (Math.random() * 9);
        }
        String today = new SimpleDateFormat("MMddHHmmssSSS").format(new Date());
        String partnerTradeNo = wxSubmchid + today + code;//
        return partnerTradeNo;
    }
}
